// Log.h
#pragma once
#include <iostream>
#include <stdarg.h>
#include <ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>

#define Info 1
#define Debug 2
#define Warning 3
#define Error 4
#define Fatal 5

#define SIZE 1024
#define LogFile "log.txt"

enum Method {
    Screen,
    Onefile,
    Classfile
};

class Log {
public:
    Log();
    ~Log();
    
    std::string levelToString(int level);  // 将日志级别转换为字符串
    void printLog(int level, const std::string &logTxt);  // 打印日志到指定文件
    void printOneFile(const std::string &logname, const std::string &logtxt);  // 打印日志到指定文件
    void operator()(int level, const char* format, ...);  // 重载()运算符，实现日志打印
    void printClassFile(int level, const std::string &logtxt);  
private:
    std::string path;
    int method;
};


Log::Log() {
    path = "./log/";
    method = Onefile;  // 默认使用Onefile方法
}

Log::~Log() {
}

std::string Log::levelToString(int level) {
    switch (level) {
        case Info:
            return "Info";
        case Debug:
            return "Debug";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            return "Unknown";
    }
}

void Log::printLog(int level, const std::string &logTxt) {
    switch (method)
    {
        case Screen:
            std::cout << logTxt << std::endl;  // 打印到显示屏
            break;
        case Onefile:
            printOneFile(LogFile, logTxt);
            break;
        case Classfile:
            printClassFile(level, logTxt);
            break;
        default:
            break;
    }

}

void Log::printOneFile(const std::string &logname, const std::string &logtxt) {
    std::string _logname = path + logname;
    int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); // "log.txt"
    if (fd < 0)
        return;
    write(fd, logtxt.c_str(), logtxt.size());
    close(fd);
}

void Log::printClassFile(int level, const std::string &logtxt)
{
    std::string filename = LogFile;
    filename += ".";
    filename += levelToString(level); // "log.txt.Debug/Warning/Fatal"
    printOneFile(filename, logtxt);
}

void Log::operator()(int level, const char* format, ...) {
    time_t t = time(nullptr);  // 获取当前时间
    char defaultBuffer[SIZE] = {0};

    struct tm* ctime = localtime(&t);  // 将时间转换为本地时间
    
    snprintf(defaultBuffer, sizeof(defaultBuffer), "%d-%d-%d %d:%d:%d [%s] ", 
        ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, 
        ctime->tm_hour, ctime->tm_min, ctime->tm_sec, 
        levelToString(level).c_str());

    va_list s;
    va_start(s, format);  // 初始化参数列表

    char alterBuffer[SIZE] = {0};
    vsnprintf(alterBuffer, sizeof(alterBuffer), format, s);  // 将格式化字符串转换为日志信息

    va_end(s);  // 结束参数列表

    char logTxt[SIZE * 2] = {0};  // 用于存储时间和日志信息的缓冲区
    snprintf(logTxt, sizeof(logTxt), "%s%s\n", defaultBuffer, alterBuffer);  // 将时间和日志信息拼接放到logTxt中

    printLog(level, logTxt);


}